﻿using System;
using System.Collections.Generic;
using System.Text;
using System.Data;
using System.Text.RegularExpressions;
using System.Data.Common;

namespace MM.Common.DBBase
{
    public abstract class DbBase
    {
        // Fields
        protected bool autoClose;
        protected StringBuilder errorMessage = new StringBuilder();
        protected DataBaseTypeEnum m_DataBaseType = DataBaseTypeEnum.Oracle;
        protected bool recordChangeSQL;
        protected int sqlParmLen = 0x200;
        protected string tableOrder = "";
        protected long transactionID = -1;
        protected int transactionOrder;

        // Methods
        protected DbBase()
        {
        }

        protected abstract bool BeginTransaction();
        protected void ClearErrorMessage()
        {
            this.errorMessage.Remove(0, this.errorMessage.Length);
        }

        protected abstract bool CommitTransaction();
        public abstract string DataSource();
        public abstract void DBClose();
        public bool ExecuteProcedure(string procedure_name)
        {
            return this.ExecuteProcedure(procedure_name, new DataParamCol(), !this.IsExistTransaction);
        }

        public bool ExecuteProcedure(string procedure_name, DataParamCol parms)
        {
            return this.ExecuteProcedure(procedure_name, parms, !this.IsExistTransaction);
        }

        public abstract bool ExecuteProcedure(string procedure_name, DataParamCol parms, bool commit);
        public bool ExecuteScalar<T>(string commandtext, ref T data)
        {
            return this.ExecuteScalar<T>(commandtext, null, ref data, false);
        }

        public bool ExecuteScalar(string commandtext, ref object obj)
        {
            return this.ExecuteScalar(commandtext, null, ref obj, false);
        }

        public bool ExecuteScalar<T>(string commandtext, DataParamCol parms, ref T data)
        {
            return this.ExecuteScalar<T>(commandtext, parms, ref data, false);
        }

        public bool ExecuteScalar<T>(string commandtext, ref T data, bool close_db)
        {
            return this.ExecuteScalar<T>(commandtext, null, ref data, close_db);
        }

        public bool ExecuteScalar(string commandtext, DataParamCol parms, ref object obj)
        {
            return this.ExecuteScalar(commandtext, parms, ref obj, false);
        }

        public bool ExecuteScalar(string commandtext, ref object obj, bool close_db)
        {
            return this.ExecuteScalar(commandtext, null, ref obj, close_db);
        }

        public bool ExecuteScalar<T>(string commandtext, DataParamCol parms, ref T data, bool close_db)
        {
            object obj2 = new object();
            if (!this.ExecuteScalar(commandtext, parms, ref obj2, close_db))
            {
                return false;
            }
            if (obj2 is DBNull)
            {
                data = default(T);
                return false;
            }
            data = (T)Convert.ChangeType(obj2, typeof(T));
            return true;
        }

        public abstract bool ExecuteScalar(string commandtext, DataParamCol parms, ref object obj, bool close_db);
        public int ExecuteSql(string commandtext)
        {
            return this.ExecuteSql(commandtext, new DataParamCol[0], 0, !this.IsExistTransaction);
        }

        public int ExecuteSql(string commandtext, object[] parmvalue)
        {
            DataParamCol sQLParm = this.GetSQLParm(commandtext, parmvalue);
            return this.ExecuteSql(commandtext, sQLParm, 0, !this.IsExistTransaction);
        }

        public int ExecuteSql(string commandtext, DataParamCol parms)
        {
            return this.ExecuteSql(commandtext, parms, 0, !this.IsExistTransaction);
        }

        public int ExecuteSql(string commandtext, bool commit)
        {
            return this.ExecuteSql(commandtext, new DataParamCol[0], 0, commit);
        }

        public int ExecuteSql(string commandtext, int nrows)
        {
            return this.ExecuteSql(commandtext, new DataParamCol[0], nrows, !this.IsExistTransaction);
        }

        public int ExecuteSql(string commandtext, DataParamCol parms, int nrows)
        {
            return this.ExecuteSql(commandtext, parms, nrows, !this.IsExistTransaction);
        }

        public int ExecuteSql(string commandtext, object[] parmvalue, int nrows)
        {
            DataParamCol sQLParm = this.GetSQLParm(commandtext, parmvalue);
            return this.ExecuteSql(commandtext, sQLParm, nrows, !this.IsExistTransaction);
        }

        public int ExecuteSql(string commandtext, object[] parmvalue, int nrows, bool commit)
        {
            DataParamCol sQLParm = this.GetSQLParm(commandtext, parmvalue);
            return this.ExecuteSql(commandtext, sQLParm, nrows, commit);
        }

        public abstract int ExecuteSql(string commandtext, DataParamCol parms, int nrows, bool commit);
        protected virtual void GetChangeParameter()
        {
            object obj2 = null;
            this.recordChangeSQL = false;
            this.tableOrder = "";
            try
            {
                string commandtext = "SELECT PARAMETER_VALUE FROM MXHLY_SYS_PARAMETER WHERE PARAMETER_TYPE_CODE = :typecode AND PARAMETER_NAME = :paraname";
                DataParamCol parms = new DataParamCol(new DataParam[] { new InputDataParam("typecode", "SYSTEM"), new InputDataParam("paraname", "RecordChangeSQL") });
                if ((this.ExecuteScalar(commandtext, parms, ref obj2) && (obj2 != null)) && !Convert.IsDBNull(obj2))
                {
                    this.recordChangeSQL = obj2.ToString() == "Y";
                }
            }
            catch
            {
            }
        }

        public int? GetCount(string sql, DataParamCol parameters)
        {
            return this.GetCount(sql, parameters, false);
        }

        public int? GetCount(string sql, DataParamCol parameters, bool close_db)
        {
            try
            {
                if (!string.IsNullOrEmpty(sql))
                {
                    int data = 0;
                    if (this.ExecuteScalar<int>(sql, parameters, ref data, close_db))
                    {
                        return new int?(data);
                    }
                    return null;
                }
                return null;
            }
            catch
            {
                return null;
            }
        }

        public abstract string GetDbDefault(string table_name, string column_name);
        public abstract DateTime GetDBTime();
        protected void GetParmsValue(DbCommand cmd, DataParamCol parms)
        {
            if (parms != null)
            {
                foreach (DataParam param in parms)
                {
                    if (param.Direction != ParameterDirection.Input)
                    {
                        param.Value = cmd.Parameters[param.Name].Value;
                    }
                }
            }
        }

        protected DataParamCol GetSQLParm(string sql, object[] parmvalue)
        {
            DataParamCol col = new DataParamCol();
            int index = 0;
            string[] strArray = Regex.Split(sql, @"[^:\w]+", RegexOptions.IgnoreCase);
            for (int i = 0; i < strArray.Length; i++)
            {
                if ((strArray[i].Length <= 1) || (strArray[i][0] != ':'))
                {
                    continue;
                }
                string paraname = strArray[i].Substring(1);
                bool flag = false;
                for (int j = 0; j < col.Count; j++)
                {
                    if (col[j].Name == paraname)
                    {
                        flag = true;
                        break;
                    }
                }
                if (!flag && (index < parmvalue.Length))
                {
                    col.Add(paraname, parmvalue[index]);
                    index++;
                }
            }
            return col;
        }

        protected virtual void GetSqlParmLen()
        {
        }

        public object GetValue(string table_name, string id_field, string id_value, string value_field)
        {
            return this.GetValue(table_name, id_field, id_value, value_field, false);
        }

        public T GetValue<T>(string table_name, string id_field, string id_value, string value_field)
        {
            object obj2 = this.GetValue(table_name, id_field, id_value, value_field, false);
            if (obj2 == null)
            {
                return default(T);
            }
            return (T)Convert.ChangeType(obj2, typeof(T));
        }

        public T GetValue<T>(string table_name, string id_field, string id_value, string value_field, bool close_db)
        {
            object obj2 = this.GetValue(table_name, id_field, id_value, value_field, close_db);
            if (obj2 == null)
            {
                return default(T);
            }
            return (T)Convert.ChangeType(obj2, typeof(T));
        }

        public object GetValue(string table_name, string id_field, string id_value, string value_field, bool close_db)
        {
            DataParamCol parms = new DataParamCol(new DataParam[] { new InputDataParam("idvalue", id_value) });
            string commandtext = "SELECT " + value_field + " FROM " + table_name + " WHERE " + id_field + " = :idvalue";
            try
            {
                object obj2 = new object();
                if (this.ExecuteScalar(commandtext, parms, ref obj2, close_db))
                {
                    return obj2;
                }
                return null;
            }
            catch
            {
                return null;
            }
        }

        public bool IsExist(string table, string field, string value)
        {
            return this.IsExist(table, field, value, false);
        }

        public bool IsExist(string table, string field, string value, bool close_db)
        {
            if ((!string.IsNullOrEmpty(table) && !string.IsNullOrEmpty(field)) && !string.IsNullOrEmpty(value))
            {
                DataParamCol parms = new DataParamCol(new DataParam[] { new InputDataParam("id", value) });
                new DataTable();
                int data = 0;
                this.ExecuteScalar<int>("SELECT COUNT(*) FROM " + table + " WHERE " + field + " = :id", parms, ref data, close_db);
                return (data > 0);
            }
            return false;
        }

        protected abstract bool Open();
        public abstract bool Open(string connectstring);
        public bool OpenConnect(string connectstring)
        {
            bool flag = true;
            this.ClearErrorMessage();
            try
            {
                if (this.Open(connectstring))
                {
                    this.GetChangeParameter();
                    this.GetSqlParmLen();
                    return flag;
                }
                flag = false;
            }
            catch (Exception exception)
            {
                flag = false;
                this.errorMessage.Append(exception.Message);
            }
            return flag;
        }

        public bool Retrieve(string[] commandtexts, ref DataTable[] dts)
        {
            DataParamCol[] parms = new DataParamCol[commandtexts.Length];
            for (int i = 0; i < commandtexts.Length; i++)
            {
                parms = new DataParamCol[0];
            }
            return this.Retrieve(commandtexts, parms, ref dts, false);
        }

        public bool Retrieve(string commandtext, ref DataTable dt)
        {
            return this.Retrieve(commandtext, new DataParamCol(), ref dt, false);
        }

        public bool Retrieve(string[] commandtexts, object[][] parmvalues, ref DataTable[] dts)
        {
            DataParamCol[] parms = new DataParamCol[parmvalues.GetLength(0)];
            for (int i = 0; i < parmvalues.GetLength(0); i++)
            {
                parms[i] = this.GetSQLParm(commandtexts[i], parmvalues[i]);
            }
            return this.Retrieve(commandtexts, parms, ref dts, false);
        }

        public bool Retrieve(string commandtext, ref DataTable dt, bool close_db)
        {
            return this.Retrieve(commandtext, new DataParamCol(), ref dt, close_db);
        }

        public bool Retrieve(string[] commandtexts, ref DataTable[] dts, bool close_db)
        {
            DataParamCol[] parms = new DataParamCol[commandtexts.Length];
            for (int i = 0; i < commandtexts.Length; i++)
            {
                parms = new DataParamCol[0];
            }
            return this.Retrieve(commandtexts, parms, ref dts, close_db);
        }

        public bool Retrieve(string commandtext, DataParamCol parm, ref DataTable dt)
        {
            return this.Retrieve(commandtext, parm, ref dt, false);
        }

        public bool Retrieve(string commandtext, object[] parmvalue, ref DataTable dt)
        {
            DataParamCol sQLParm = this.GetSQLParm(commandtext, parmvalue);
            return this.Retrieve(commandtext, sQLParm, ref dt, false);
        }

        public bool Retrieve(string[] commandtexts, DataParamCol[] parms, ref DataTable[] dts)
        {
            return this.Retrieve(commandtexts, parms, ref dts, false);
        }

        public bool Retrieve(string[] commandtexts, object[][] parmvalues, ref DataTable[] dts, bool close_db)
        {
            DataParamCol[] parms = new DataParamCol[parmvalues.GetLength(0)];
            for (int i = 0; i < parmvalues.GetLength(0); i++)
            {
                parms[i] = this.GetSQLParm(commandtexts[i], parmvalues[i]);
            }
            return this.Retrieve(commandtexts, parms, ref dts, close_db);
        }

        public abstract bool Retrieve(string commandtext, DataParamCol parm, ref DataTable dt, bool close_db);
        public bool Retrieve(string commandtext, object[] parmvalue, ref DataTable dt, bool close_db)
        {
            DataParamCol sQLParm = this.GetSQLParm(commandtext, parmvalue);
            return this.Retrieve(commandtext, sQLParm, ref dt, close_db);
        }

        public abstract bool Retrieve(string[] commandtexts, DataParamCol[] parms, ref DataTable[] dts, bool close_db);
        public bool RetrieveProcedure(string procedure_name, DataParamCol parms, ref DataTable dt)
        {
            return this.RetrieveProcedure(procedure_name, parms, ref dt, false);
        }

        public abstract bool RetrieveProcedure(string procedure_name, DataParamCol parms, ref DataTable dt, bool close_db);
        protected abstract bool RollbackTransaction();
        public int RunSql(string[] commandtexts)
        {
            int[] nrows = new int[commandtexts.Length];
            for (int i = 0; i < nrows.Length; i++)
            {
                nrows[i] = 0;
            }
            return this.RunSql(commandtexts, new DataParamCol[0], nrows, !this.IsExistTransaction);
        }

        public int RunSql(string[] commandtexts, object[][] parmvalues)
        {
            int[] nrows = new int[commandtexts.Length];
            DataParamCol[] parms = new DataParamCol[commandtexts.Length];
            for (int i = 0; i < nrows.Length; i++)
            {
                nrows[i] = 0;
                parms[i] = this.GetSQLParm(commandtexts[i], parmvalues[i]);
            }
            return this.RunSql(commandtexts, parms, nrows, !this.IsExistTransaction);
        }

        public int RunSql(string[] commandtexts, DataParamCol[] parms)
        {
            int[] nrows = new int[commandtexts.Length];
            for (int i = 0; i < nrows.Length; i++)
            {
                nrows[i] = 0;
            }
            return this.RunSql(commandtexts, parms, nrows, !this.IsExistTransaction);
        }

        public int RunSql(string[] commandtexts, int[] nrows)
        {
            return this.RunSql(commandtexts, new DataParamCol[0], nrows, !this.IsExistTransaction);
        }

        public int RunSql(string[] commandtexts, object[][] parmvalues, int[] nrows)
        {
            DataParamCol[] parms = new DataParamCol[commandtexts.Length];
            for (int i = 0; i < nrows.Length; i++)
            {
                parms[i] = this.GetSQLParm(commandtexts[i], parmvalues[i]);
            }
            return this.RunSql(commandtexts, parms, nrows, !this.IsExistTransaction);
        }

        public int RunSql(string[] commandtexts, DataParamCol[] parms, int[] nrows)
        {
            return this.RunSql(commandtexts, parms, nrows, !this.IsExistTransaction);
        }

        public abstract int RunSql(string[] commandtexts, DataParamCol[] parms, int[] nrows, bool commit);
        public int RunSql(string[] commandtexts, object[][] parmvalues, int[] nrows, bool commit)
        {
            DataParamCol[] parms = new DataParamCol[commandtexts.Length];
            for (int i = 0; i < nrows.Length; i++)
            {
                parms[i] = this.GetSQLParm(commandtexts[i], parmvalues[i]);
            }
            return this.RunSql(commandtexts, parms, nrows, commit);
        }

        public virtual bool TransactionBegin()
        {
            bool flag = true;
            this.ClearErrorMessage();
            if (!this.IsOpen)
            {
                try
                {
                    if (this.Open())
                    {
                        this.GetChangeParameter();
                    }
                    else
                    {
                        flag = false;
                    }
                }
                catch (Exception exception)
                {
                    this.errorMessage.Append(exception.Message);
                    flag = false;
                }
            }
            if (!flag)
            {
                return flag;
            }
            if (this.BeginTransaction())
            {
                this.transactionID = -1;
                if (!this.recordChangeSQL)
                {
                    return flag;
                }
                try
                {
                    int data = 0;
                    this.ExecuteScalar<int>("SELECT F_GET_TRANSACTION_NO() FROM DUAL", ref data);
                    this.transactionID = data;
                    this.transactionOrder = 1;
                    return flag;
                }
                catch (Exception exception2)
                {
                    this.errorMessage.Append(exception2.Message);
                    return false;
                }
            }
            return false;
        }

        public bool TransactionCommit()
        {
            return this.TransactionCommit(false);
        }

        public bool TransactionCommit(bool close_db)
        {
            if (!this.CommitTransaction())
            {
                return false;
            }
            this.transactionID = -1;
            if (this.autoClose && close_db)
            {
                this.DBClose();
            }
            return true;
        }

        public bool TransactionRollback()
        {
            return this.TransactionRollback(false);
        }

        public bool TransactionRollback(bool close_db)
        {
            if (!this.RollbackTransaction())
            {
                return false;
            }
            this.transactionID = -1;
            if (this.autoClose && close_db)
            {
                this.DBClose();
            }
            return true;
        }

        public bool Update(DataTable dt, string[] keycols)
        {
            if (keycols == null)
            {
                keycols = new string[0];
            }
            return this.Update(dt, keycols, new string[0], !this.IsExistTransaction);
        }

        public bool Update(DataTable dt, string[] keycols, bool commit)
        {
            if (keycols == null)
            {
                keycols = new string[0];
            }
            return this.Update(dt, keycols, new string[0], commit);
        }

        public bool Update(DataTable dt, string[] keycols, string[] nocols)
        {
            return this.Update(dt, keycols, nocols, !this.IsExistTransaction);
        }

        public bool Update(DataTable dt, string[] keycols, string[] nocols, bool commit)
        {
            bool flag = true;
            this.ClearErrorMessage();
            if (dt.TableName == "")
            {
                this.errorMessage.Append("未设置表名");
                return false;
            }
            DataTable changes = dt.GetChanges();
            if (changes == null)
            {
                return true;
            }
            if (nocols == null)
            {
                nocols = new string[0];
            }
            string str = "INSERT INTO " + dt.TableName + " (";
            string str2 = " VALUES (";
            string str3 = "UPDATE " + dt.TableName + " SET ";
            string str4 = "DELETE FROM " + dt.TableName;
            string str5 = " WHERE ";
            string[] strArray = new string[dt.Columns.Count - nocols.Length];
            int index = 0;
            for (int i = 0; i < dt.Columns.Count; i++)
            {
                if (nocols != null)
                {
                    bool flag2 = false;
                    for (int k = 0; k < nocols.Length; k++)
                    {
                        if (nocols[k].ToUpper() == dt.Columns[i].ColumnName.ToUpper())
                        {
                            flag2 = true;
                            break;
                        }
                    }
                    if (flag2)
                    {
                        continue;
                    }
                }
                strArray[index] = dt.Columns[i].ColumnName.ToLower();
                index++;
                str = str + dt.Columns[i].ColumnName + ",";
                str2 = str2 + ":" + dt.Columns[i].ColumnName.ToLower() + ",";
                string str8 = str3;
                str3 = str8 + dt.Columns[i].ColumnName + " = :" + dt.Columns[i].ColumnName.ToLower() + ",";
            }
            str = str.Substring(0, str.Length - 1) + ")";
            str2 = str2.Substring(0, str2.Length - 1) + ")";
            str3 = str3.Substring(0, str3.Length - 1);
            for (int j = 0; j < keycols.Length; j++)
            {
                str5 = str5 + keycols[j] + " = :o_" + keycols[j].ToLower();
                if (j < (keycols.Length - 1))
                {
                    str5 = str5 + " AND ";
                }
            }
            try
            {
                if (commit)
                {
                    this.TransactionBegin();
                }
                for (int m = 0; m < changes.Rows.Count; m++)
                {
                    int num7;
                    int num8;
                    string commandtext = "";
                    DataParamCol parms = new DataParamCol();
                    DataRowState rowState = changes.Rows[m].RowState;
                    if (rowState != DataRowState.Added)
                    {
                        if (rowState == DataRowState.Deleted)
                        {
                            goto Label_02F6;
                        }
                        if (rowState == DataRowState.Modified)
                        {
                            goto Label_0348;
                        }
                    }
                    else
                    {
                        for (int num6 = 0; num6 < strArray.Length; num6++)
                        {
                            parms.Add(strArray[num6], changes.Rows[m][strArray[num6]]);
                        }
                        commandtext = str + str2;
                    }
                    goto Label_03CB;
                Label_02F6:
                    num7 = 0;
                    while (num7 < keycols.Length)
                    {
                        parms.Add("o_" + keycols[num7], changes.Rows[m][keycols[num7], DataRowVersion.Original]);
                        num7++;
                    }
                    commandtext = str4 + str5;
                    goto Label_03CB;
                Label_0348:
                    num8 = 0;
                    while (num8 < strArray.Length)
                    {
                        parms.Add(strArray[num8], changes.Rows[m][strArray[num8]]);
                        num8++;
                    }
                    for (int n = 0; n < keycols.Length; n++)
                    {
                        parms.Add("o_" + keycols[n], changes.Rows[m][keycols[n], DataRowVersion.Original]);
                    }
                    commandtext = str3 + str5;
                Label_03CB:
                    if (this.ExecuteSql(commandtext, parms, 1, false) != 1)
                    {
                        string str7 = this.errorMessage.ToString();
                        if (commit)
                        {
                            this.TransactionRollback();
                        }
                        flag = false;
                        this.errorMessage.Append(str7);
                        break;
                    }
                }
                if (!flag)
                {
                    return flag;
                }
                if (commit)
                {
                    this.TransactionCommit();
                }
                dt.AcceptChanges();
            }
            catch (Exception exception)
            {
                this.errorMessage.Append(exception.Message);
                flag = false;
                if (commit)
                {
                    this.TransactionRollback();
                }
            }
            return flag;
        }

        // Properties
        public bool AutoClose
        {
            get
            {
                return this.autoClose;
            }
            set
            {
                this.autoClose = value;
            }
        }

        public string ChangeSQLTableOrder
        {
            set
            {
                this.tableOrder = value;
            }
        }

        public DataBaseTypeEnum DataBaseType
        {
            get
            {
                return this.m_DataBaseType;
            }
        }

        public string ErrorMessage
        {
            get
            {
                return this.errorMessage.ToString();
            }
        }

        public virtual bool IsExistTransaction
        {
            get
            {
                return false;
            }
        }

        public virtual bool IsOpen
        {
            get
            {
                return false;
            }
        }
    }
}
